home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / bbs / pub_acc.taz / pub_acc / bank.c next >
Encoding:
C/C++ Source or Header  |  1992-12-09  |  16.8 KB  |  939 lines

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <pwd.h>
  4. #include <time.h>
  5. #include <signal.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8.  
  9. #define OPENDELAY 7        /* Days to wait before opening an account */
  10. #define INITBALANCE 5        /* How much to give new account openers */
  11.  
  12. /* Files where bank records are kept */
  13. char *transfile = "/home/games/bank/trans";        /* Transaction records */
  14. char *bankfile = "/home/games/bank/bank";    /* Current balances */
  15. char *bankers = "/home/games/bank/bankers";  /* List of Bankers */
  16.  
  17. #ifdef FILELOCK
  18. char *translock = "/home/games/bank/t.lock";
  19. char *banklock = "/home/games/bank/b.lock";
  20. #else
  21. #define done(r)        exit(r)
  22. #endif FILELOCK
  23.  
  24. /* Names of monetary units and of the bank */
  25. char *bankname = "the First National Bank of The R.I.P.";
  26. char *unit = "fuzzy-nibble";
  27. char *units = "fibblies";
  28. char *abbr = "fb";
  29.  
  30. /* Structure of transaction file entry */
  31. struct trans_ent {
  32.     int to_uid;        /* Uid of person affected */
  33.     char code;        /* See below */
  34.     char fr_id[8];        /* Login id of donor */
  35.     char why[40];        /* Donor's reason why */
  36.     long amount;        /* Number of units */
  37.     };
  38.  
  39. /* Transaction codes */
  40. #define TR_NONE    0        /* Not a real entry */
  41. #define TR_XFER 1        /* From another user */
  42. #define TR_GIFT 2        /* Bestowal from the government */
  43. #define TR_FINE 3        /* Fine from the government */
  44.  
  45. char *trname[4] = {"bug","transfer","gift","fine"};
  46.  
  47. /* Global variables */
  48. int myuid;        /* Customer's uid number */
  49. char myid[9];        /* Customer's login name */
  50. int banker;        /* Is the customer a banker? */
  51. int report;        /* Should I just report new transactions? */
  52. long mybal;        /* Customer's current balance */
  53. char buf[42];        /* Input buffer */
  54. char hisid[42];        /* His login name */
  55. long tm;        /* Current time */
  56. int bf;            /* Bank file stream */
  57. int tf;            /* Transaction file stream */
  58.  
  59. struct passwd *getpwuid(), *getpwnam();
  60. struct tm *localtime();
  61. long time(),atol(),lseek();
  62. char *ctime();
  63.  
  64. main(argc,argv)
  65. int argc;
  66. char **argv;
  67. {
  68. struct passwd *pwd;
  69. int i;
  70.  
  71.     if ((bf = open(bankfile,O_RDWR|O_CREAT,0700)) < 0)
  72.     {
  73.         printf("Error: Cannot open bank file %s\n",bankfile);
  74.         done(1);
  75.     }
  76.     if ((tf = open(transfile,O_RDWR|O_CREAT,0600)) < 0)
  77.     {
  78.         printf("Cannot open transaction file %s\n",transfile);
  79.         done(1);
  80.     }
  81.  
  82.     tm = time((long *)0);
  83.  
  84.     pwd = getpwuid(myuid = getuid());
  85.     strncpy(myid,pwd->pw_name,8);
  86.     banker = am_banker(myid);
  87.  
  88.     if (argc > 1)
  89.     {
  90.     if (argv[1][0] != '-')
  91.     {
  92.         for (i=1; i<argc; i++)
  93.         {
  94.         setpwent();
  95.         printf("%8s ",argv[i]);
  96.         if ((pwd = getpwnam(argv[i])) == NULL)
  97.             printf("not found\n");
  98.         else if (balance(pwd->pw_uid,&mybal))
  99.             printf("has no account\n");
  100.         else
  101.             printf("balance = %ld%s\n",mybal,abbr);
  102.         }
  103.         done(0);
  104.     }
  105.  
  106.     switch(argv[1][1])
  107.     {
  108.     case 'w':
  109.         wealthy();
  110.         exit(0);
  111.     case 'a':
  112.         listall();
  113.         exit(0);
  114.     case 'r':
  115.         report = 1;
  116.         banker = 0;
  117.         break;
  118.     case 't':
  119.         parsetrans(TR_XFER,argc,argv);
  120.         done(0);
  121.     case 'b':
  122.         parsetrans(TR_GIFT,argc,argv);
  123.         done(0);
  124.     case 'f':
  125.         parsetrans(TR_FINE,argc,argv);
  126.         done(0);
  127.     case 'o':
  128.     case 'c':
  129.         if (!banker)
  130.         {
  131.             printf("You're not a banker!\n");
  132.         done(1);
  133.         }
  134.         if (argc != 3)
  135.         {
  136.         printf("usage: %s -%c userid\n",argv[0],argv[1][1]);
  137.         done(1);
  138.         }
  139.         setpwent();
  140.         if ((pwd = getpwnam(argv[2])) == NULL)
  141.         {
  142.         printf("Can't find user %s\n",argv[2]);
  143.         done(1);
  144.         }
  145.         if (argv[1][1] == 'o')
  146.         addbalance(pwd->pw_uid,0L);
  147.         else
  148.         closeaccount(pwd->pw_uid);
  149.         done(0);
  150.     default:
  151.         printf("Legal options are -w -a -t ");
  152.         if (banker) printf("-b -f -o -c ");
  153.         printf("and -r\n");
  154.         done(1);
  155.     }
  156.     }
  157.  
  158.     if (banker)
  159.     {
  160.     struct tm *tod;
  161.     printf("Good ");
  162.     tod = localtime(&tm);
  163.     if (tod->tm_hour < 12)
  164.         printf("Morning");
  165.     else if (tod->tm_hour < 18)
  166.         printf("Afternoon");
  167.     else
  168.         printf("Evening");
  169.     printf(", Banker %s\n",myid);
  170.     }
  171.  
  172.     if (!report)
  173.     printf("Welcome to %s\n\n",bankname);
  174.  
  175.     checkme();        /* Only returns if user has open account */
  176.  
  177.     printf("Transactions since your last visit:  ");
  178.     scantrans(myuid,0);
  179.  
  180.     printf("\nCurrent balance: %ld%s\n",mybal,abbr);
  181.  
  182.     if (!report)
  183.     {
  184.     if (banker)
  185.         dobank();
  186.     else if (mybal > 0)
  187.     {
  188.         printf("\nWould you like to transfer funds to another user? ");
  189.         fgets(buf,40,stdin);
  190.         if (buf[0] != 'n' && buf[0] != 'N')
  191.         asktrans(TR_XFER,NULL);
  192.     }
  193.     }
  194.     done(0);
  195. }
  196.  
  197. /*
  198.  * Register the user
  199.  */
  200.  
  201. checkme()
  202. {
  203. int ch;
  204.  
  205.     switch (balance(myuid,&mybal))
  206.     {
  207.     case 1:
  208.     if (report)
  209.     {
  210.         printf("You have no account\n");
  211.         done(0);
  212.     }
  213.     if (banker)
  214.     {
  215.         addbalance(myuid,0L);
  216.         mybal = INITBALANCE;
  217.         return;
  218.     }
  219.     printf("Hello %s, would you like to open an account? ",myid);
  220.     if ((ch = getchar()) == 'n' || ch == 'N')
  221.     {
  222.         printf("Goodbye then...\n");
  223.         done(0);
  224.     }
  225.     if (ch != '\n')
  226.         while (getchar() != '\n')
  227.             ;
  228.     openaccount(myuid);
  229.     printf("Very well...\nThere will be a %d day delay ",OPENDELAY);
  230.     printf("before your account can be opened.\n    Thank you!\n");
  231.     done(0);
  232.     case 2:        /* Applicant awaiting approval */
  233.     if (mybal > tm)
  234.     {
  235.         if (report)
  236.         {
  237.         printf("Your account will be open after %s",ctime(&mybal));
  238.             done(0);
  239.         }
  240.         else if (!banker)
  241.         {
  242.         printf("Sorry, the paperwork on your new account has not ");
  243.         printf("been completed\nPlease come back after %s",
  244.             ctime(&mybal));
  245.         printf("    Thank you!\n");
  246.         done(0);
  247.         }
  248.     }
  249.     /* If time is up, initialize the account */
  250.     addbalance(myuid,0L);
  251.     mybal = INITBALANCE;
  252.     break;
  253.     }
  254. }
  255.  
  256.  
  257. parsetrans(type,argc,argv)
  258. int type, argc;
  259. char **argv;
  260. {
  261. long amt;
  262. struct passwd *pwd;
  263.  
  264.     if (type != TR_XFER && !banker)
  265.     {
  266.         printf("You're not a banker!\n");
  267.         return;
  268.     }
  269.  
  270.     if (argc < 4 || argc > 5)
  271.     {
  272.         printf("usage: %s [-t",argv[0]);
  273.         if (banker) printf(" -b -f");
  274.         printf("] who amount [reason]\n");
  275.         return;
  276.     }
  277.  
  278.     setpwent();
  279.     if ((pwd = getpwnam(argv[2])) == NULL)
  280.     {
  281.         printf("No user %s\n",argv[2]);
  282.         return;
  283.     }
  284.  
  285.     if ((amt = atol(argv[3])) <= 0)
  286.     {
  287.         printf("Bad amount %s\n",argv[3]);
  288.         return;
  289.     }
  290.  
  291.     checkme();
  292.  
  293.     if (type == TR_XFER && amt > mybal)
  294.     {
  295.         printf("You don't have that much money\n");
  296.         return;
  297.     }
  298.  
  299.     if (myuid == pwd->pw_uid)
  300.     {
  301.         printf("Can't transfer money to yourself\n");
  302.         return;
  303.     }
  304.  
  305.     if (argc == 4)
  306.     {
  307.         buf[0] = '\0';
  308.         dotrans(type,pwd->pw_uid,amt,buf);
  309.     }
  310.     else
  311.         dotrans(type,pwd->pw_uid,amt,argv[4]);
  312. }
  313.  
  314.  
  315. /*
  316.  *  The banker's secretary.
  317.  */
  318.  
  319. dobank()
  320. {
  321. char *w;
  322.     printf("\nYou may either:\n");
  323.     printf("   Transfer some of your own money to another user\n");
  324.     printf("   Fine another user some money\n");
  325.     printf("   Bestow some money on another user\n");
  326.     printf("   Open an account for another user\n");
  327.     printf("   Close a users account\n");
  328.     printf("   Report on an account's balance\n");
  329.     printf("   Quit\n");
  330.  
  331.     for (;;)
  332.     {
  333.         printf(": ");
  334.         buf[0] = '\0';
  335.         fgets(buf,40,stdin);
  336.         for (w = buf; *w != '\0'; w++)
  337.             if (*w == ' ')
  338.             {
  339.                 w++;
  340.                 w[strlen(w)-1] = '\0';
  341.                 break;
  342.             }
  343.         switch(buf[0])
  344.         {
  345.         case 'T': case 't':
  346.             asktrans(TR_XFER,w);
  347.             break;
  348.         case 'F': case 'f':
  349.             asktrans(TR_FINE,w);
  350.             break;
  351.         case 'B': case 'b':
  352.             asktrans(TR_GIFT,w);
  353.             break;
  354.         case 'O': case 'o':
  355.             askopen(w);
  356.             break;
  357.         case 'C': case 'c':
  358.             askclose(w);
  359.             break;
  360.         case 'R': case 'r':
  361.             askreport(w);
  362.         case '\n':
  363.             break;
  364.         case '\0':
  365.             putchar('\n');
  366.         case 'Q': case 'q':
  367.             return;
  368.         default:
  369.             printf("Pardon me?\n");
  370.             break;
  371.         }
  372.     }
  373. }
  374.  
  375. /*
  376.  * Ask user about a transaction of type type.
  377.  */
  378.  
  379. asktrans(type,did)
  380. int type;
  381. char *did;
  382. {
  383. int hisuid;
  384. long hisbal,amt;
  385. int n;
  386.  
  387.     /* Find out who to pay */
  388.     if (did == NULL || *did == '\0')
  389.     {
  390.     switch (type)
  391.     {
  392.     case TR_XFER:
  393.         printf("Transfer to");
  394.         break;
  395.     case TR_GIFT:
  396.         printf("Bestow upon");
  397.         break;
  398.     case TR_FINE:
  399.         printf("Fine");
  400.         break;
  401.     }
  402.  
  403.     printf(" whom? ");
  404.     }
  405.     if ((hisuid = getwho(did)) < 0)
  406.         return;
  407.  
  408.     if (hisuid == myuid)
  409.     {
  410.     printf("Why, that's you!\n");
  411.     return;
  412.     }
  413.  
  414.     /* Get his account status and balance */
  415.     switch(balance(hisuid,&hisbal))
  416.     {
  417.     case 1:
  418.     if (!banker)
  419.     {
  420.         printf("%s has not applied for an account\n",hisid);
  421.         printf("However, we will open one in their name in %d days\n",
  422.         OPENDELAY);
  423.         openaccount(hisuid);
  424.         return;
  425.     }
  426.     addbalance(hisuid,0L);
  427.     break;
  428.     case 2:
  429.     if (!banker && hisbal < tm)
  430.     {
  431.         printf("%s's account will be open on %s",hisid,ctime(&hisbal));
  432.         return;
  433.     }
  434.     addbalance(hisuid,0L);
  435.     break;
  436.     }
  437.  
  438.     /* Find out how much to pay him */
  439.     printf("How many %s? ",units);
  440.     fgets(buf,40,stdin);
  441.     amt = atol(buf);
  442.  
  443.     if (amt <= 0) return;
  444.  
  445.     if (type == TR_XFER && amt > mybal)
  446.     {
  447.     printf("You only have %ld %s\n",mybal,(mybal == 1)?unit:units);
  448.     return;
  449.     }
  450.  
  451.     /* Get a short explaination message */
  452.     for (;;)
  453.     {
  454.     printf("What for? ");
  455.     fgets(buf,40,stdin);
  456.     n = strlen(buf);
  457.     if (buf[n-1] == '\n') break;
  458.     printf("Only 40 characters, please.\n");
  459.     while (getchar() != '\n')
  460.         ;
  461.     }
  462.     buf[n-1] = '\0';
  463.  
  464.     dotrans(type,hisuid,amt,buf);
  465. }
  466.  
  467.  
  468. /*
  469.  * Record a transaction of type type to user uid of amount amt for reason
  470.  * reason.
  471.  */
  472.  
  473. dotrans(type,uid,amt,reason)
  474. int type,uid;
  475. long amt;
  476. char *reason;
  477. {
  478. struct trans_ent tr;
  479.  
  480.     /* Assemble the transaction record */
  481.     tr.code = type;
  482.     tr.to_uid = uid;
  483.     tr.amount = amt;
  484.     strncpy(tr.fr_id,myid,8);
  485.     strncpy(tr.why,reason,40);
  486.  
  487.     signal(SIGINT,SIG_IGN);
  488.     signal(SIGQUIT,SIG_IGN);
  489.  
  490.     if (type == TR_XFER) addbalance(myuid,-amt);
  491.     addbalance(uid,(type == TR_FINE)?-amt:amt);
  492.  
  493.     transaction(tr);
  494.  
  495.     signal(SIGINT,SIG_DFL);
  496.     signal(SIGQUIT,SIG_DFL);
  497. }
  498.  
  499.  
  500. /*
  501.  * Instantly open an account for someone, speeding up the paper work.
  502.  */
  503.  
  504. askopen(did)
  505. char *did;
  506. {
  507. int hisuid;
  508.  
  509.     /* Find out whose account to open */
  510.     if (did == NULL || *did == '\0')
  511.     printf("Open for whom? ");
  512.     if ((hisuid = getwho(did)) < 0)
  513.     return;
  514.  
  515.     addbalance(hisuid,0L);
  516. }
  517.  
  518. askclose(did)
  519. char *did;
  520. {
  521. int hisuid;
  522.  
  523.     /* Find out whose account to open */
  524.     if (did == NULL || *did == '\0')
  525.     printf("Close whom? ");
  526.     if ((hisuid = getwho(did)) < 0)
  527.     return;
  528.  
  529.     closeaccount(hisuid);
  530. }
  531.  
  532.  
  533. /*
  534.  * Report on another user
  535.  */
  536.  
  537. askreport(did)
  538. char *did;
  539. {
  540. int hisuid;
  541. long amt;
  542.  
  543.     /* Find out whose account to report */
  544.     if (did == NULL || *did == '\0')
  545.     printf("Report on whom? ");
  546.     if ((hisuid = getwho(did)) < 0)
  547.     return;
  548.  
  549.     switch (balance(hisuid,&amt))
  550.     {
  551.     case 1:
  552.     printf("no account\n");
  553.     break;
  554.     case 2:
  555.     printf("account opens on %s",ctime(&amt));
  556.     break;
  557.     case 0:
  558.     printf("balance =%3ld%s\n",amt,abbr);
  559.     break;
  560.     }
  561. }
  562.  
  563. /*
  564.  * Find a free spot in the transaction file and put a new transaction in it.
  565.  * take care to handle files that have been truncated to odd lengths by disk
  566.  * full errors.
  567.  */
  568.  
  569. transaction(tr)
  570. struct trans_ent tr;
  571. {
  572. int n;
  573. struct trans_ent otr;
  574.  
  575.     lseek(tf,0L,0);
  576. #ifdef LOCKFILE
  577.     setlock(1);
  578. #else
  579. #endif LOCKFILE
  580.  
  581.     /* Skip to first null entry, or EOF */
  582.     while((n = read(tf,&otr,sizeof(otr))) == sizeof(otr) &&
  583.           otr.code != TR_NONE)
  584.         ;
  585.  
  586.     /* If not at EOF, rewind to beginning of last read */
  587.     if (n != 0) lseek(tf,(long) -n, 1);
  588.  
  589.     write(tf,&tr,sizeof(tr));
  590.  
  591. #ifdef    LOCKFILE
  592.     unlock(1);
  593. #else
  594.     lseek(tf,0L,0);
  595. #endif    LOCKFILE
  596. }
  597.  
  598. /*
  599.  * Read in someone's name, and return his uid.  Return -1 if a bad name is
  600.  * given.
  601.  */
  602.  
  603. getwho(did)
  604. char *did;
  605. {
  606. struct passwd *pwd;
  607.  
  608.     if (did == NULL || *did == '\0')
  609.     {
  610.         fgets(hisid,40,stdin);
  611.         hisid[strlen(hisid)-1] = '\0';
  612.     }
  613.     else
  614.         strcpy(hisid,did);
  615.  
  616.     setpwent();
  617.     if ((pwd = getpwnam(hisid)) == NULL)
  618.     {
  619.         printf("No such user (%s)\n",hisid);
  620.         return(-1);
  621.     }
  622.     return(pwd->pw_uid);
  623. }
  624.  
  625. /*
  626.  * Report all tranactions involving uid which have not been previously
  627.  * reported.  Transaction records are set to null after they have been
  628.  * printed.  If silent is set, nothing is printed.
  629.  */
  630.  
  631. scantrans(uid,silent)
  632. int uid;
  633. int silent;
  634. {
  635. struct trans_ent tr;
  636. long offset;
  637. int someflag = 0;
  638.  
  639.     lseek(tf,offset = 0L,0);
  640.     while (read(tf,&tr,sizeof(tr)) == sizeof(tr))
  641.     {
  642.     if (tr.code != TR_NONE && tr.to_uid == uid)
  643.     {
  644.         if (!silent)
  645.         {
  646.         someflag = 1;
  647.         printf("\n%7ld%s %s from %0.8s",tr.amount,abbr,
  648.             trname[tr.code],tr.fr_id);
  649.         if (tr.why[0] != '\0')
  650.             printf(" for %0.40s",tr.why);
  651.         }
  652.  
  653.         tr.code = TR_NONE;
  654.         lseek(tf,offset,0);
  655.         write(tf,&tr,sizeof(tr));
  656.     }
  657.     offset += sizeof(tr);
  658.     }
  659.  
  660.     if (!someflag && !silent)
  661.     printf("None");
  662. }
  663.  
  664.  
  665. /*
  666.  * Place a user's bank balance in *bal.  Function returns 0 if successful,
  667.  * 1 if that user hasn't requested an account, and 2 if the account has been
  668.  * requested, but not opened.  In the latter case, *bal contains the date on
  669.  * which it will be opened.
  670.  */
  671.  
  672. balance(uid,bal)
  673. int uid;
  674. long *bal;
  675. {
  676.  
  677.     if (lseek(bf,((long)uid)*sizeof(long),0) < 0)
  678.         return(1);
  679.  
  680.     if (read(bf,bal,sizeof(long)) != sizeof(long))
  681.         return(1);
  682.  
  683.     if ((*bal % 2) == 0)
  684.         return((*bal == 0)?1:2);
  685.  
  686.     *bal /= 2;
  687.     return(0);
  688. }
  689.  
  690. /*
  691.  * Write a new value into a user's account.
  692.  */
  693.  
  694. writebalance(uid,bal)
  695. int uid;
  696. long bal;
  697. {
  698.     if (lseek(bf,((long)uid)*sizeof(long),0) >= 0)
  699.         write(bf,&bal,sizeof(long));
  700. }
  701.  
  702. /*
  703.  * Increase the balance of uid's account by bal.  Open it and put in the
  704.  * initial deposit if it was not open.
  705.  */
  706.  
  707. addbalance(uid,bal)
  708. int uid;
  709. long bal;
  710. {
  711. long oldbal;
  712.     if (lseek(bf,((long)uid)*sizeof(long),0) < 0)
  713.         return;
  714.  
  715. #ifdef LOCKFILE
  716.     setlock(0);
  717. #else
  718. #endif LOCKFILE
  719.  
  720.     if (read(bf,&oldbal,sizeof(long)) != sizeof(long) || (oldbal % 2) == 0)
  721.         oldbal = (long)INITBALANCE;
  722.     else
  723.         oldbal /= 2;
  724.  
  725.     writebalance(uid,(bal+oldbal)*2+1);
  726.  
  727. #ifdef LOCKFILE
  728.     unlock(0);
  729. #else
  730.     lseek(bf,-(long)sizeof(long),1);
  731. #endif LOCKFILE
  732. }
  733.  
  734. /*
  735.  * Create an account with the usual time lag.
  736.  */
  737.  
  738. openaccount(uid)
  739. int uid;
  740. {
  741. long tm,time();
  742. #define SECSPERDAY 86400L;
  743.  
  744.     tm = time((long *)0) + OPENDELAY*SECSPERDAY;
  745.     if ((tm % 2) == 1) tm--;
  746.     writebalance(uid,tm);
  747. }
  748.  
  749. closeaccount(uid)
  750. int uid;
  751. {
  752.     writebalance(uid,0L);
  753.     scantrans(uid,1);
  754. }
  755.  
  756. /*
  757.  * List the 10 wealthiest users.
  758.  */
  759.  
  760. wealthy()
  761. {
  762. struct passwd *pwd;
  763. struct {
  764.     int uid;
  765.     long bucks;
  766.     } rich[10];
  767. int n=0,i;
  768. long new;
  769. int cuid;
  770.  
  771.     lseek(bf,0L,0);
  772.     
  773.     if (read(bf,&new,sizeof(new)) != sizeof(new))
  774.         return;
  775.     
  776.     rich[0].uid = 0;
  777.     rich[0].bucks = new;
  778.  
  779.     for (cuid = 1; read(bf,&new,sizeof(new)) == sizeof(new); cuid++)
  780.     {
  781.     if ((new % 2) == 0) continue;
  782.     new = (new-1)/2;
  783.  
  784.     for (i = n; i > 0 && new > rich[i-1].bucks; i--)
  785.     {
  786.         if (i < 10)
  787.         {
  788.         rich[i].uid = rich[i-1].uid;
  789.         rich[i].bucks = rich[i-1].bucks;
  790.         }
  791.     }
  792.     if (i < 10)
  793.     {
  794.         rich[i].uid = cuid;
  795.         rich[i].bucks = new;
  796.         if (n < 10) n++;
  797.     }
  798.     }
  799.  
  800.     for (i = 0; i < n; i++)
  801.     {
  802.     setpwent();
  803.     if ((pwd = getpwuid(rich[i].uid)) == NULL)
  804.         closeaccount(rich[i].uid);
  805.     else
  806.         printf("%2d: %8.8s%12ld%s\n",i+1,pwd->pw_name,rich[i].bucks,abbr);
  807.     }
  808. }
  809.  
  810. listall()
  811. {
  812. struct passwd *pwd;
  813. long bal;
  814. int cuid;
  815.  
  816.     lseek(bf,0L,0);
  817.     
  818.     for (cuid = 0; read(bf,&bal,sizeof(bal)) == sizeof(bal); cuid++)
  819.     {
  820.     if ((bal % 2) == 0) continue;
  821.     bal = (bal-1)/2;
  822.     setpwent();
  823.     if ((pwd = getpwuid(cuid)) == NULL)
  824.         closeaccount(cuid);
  825.     else
  826.         printf("%8.8s%12ld%s\n",pwd->pw_name,bal,abbr);
  827.     }
  828. }
  829.  
  830. #ifdef LOCKFILE
  831. /*
  832.  * Create a lockfile.  If which is 0, this is the bank lock file.  If which
  833.  * is 1, it is the transaction lockfile.
  834.  */
  835.  
  836. long clock[2] = { 0L , 0L };
  837.  
  838. setlock(which)
  839. int which;
  840. {
  841. int lf;
  842. register int trys = 0;
  843. struct stat sb;
  844. char *lockfile = which?translock:banklock;
  845.  
  846.     /* Already locked? */
  847.     if (clock[which])
  848.         return;
  849.  
  850.     /* Do exclusive open on file */
  851.     while ((lf = open(lockfile,O_RDONLY|O_CREAT|O_EXCL,0700)) < 0)
  852.     {
  853.         /* Examine existing lock file */
  854.         if (stat(lockfile,&sb))
  855.         {
  856.             printf("Can't create lockfile %s\n",lockfile);
  857.             done(1);
  858.         }
  859.         /* If more than 5 minutes old, kill it */
  860.         if (sb.st_ctime + 300 < time((long *)0))
  861.         {
  862.             printf("Blasting old %s lockfile\n",
  863.                 which?"transaction":"bank");
  864.             if (unlink(lockfile))
  865.             {
  866.                 printf("blast failed\n");
  867.                 done(1);
  868.             }
  869.             continue;
  870.         }
  871.         /* Wait up to 15 seconds for old lockfile go away */
  872.         else if (trys++ < 5)
  873.             sleep(3);
  874.         else
  875.         {
  876.             /* Give up waiting */
  877.             printf("The bank is very busy right now.\n");
  878.             printf("Please try later.\n");
  879.             done(1);
  880.         }
  881.     }
  882.  
  883.     /* Record the time at which I create the file */
  884.     fstat(lf,&sb);
  885.     clock[which] = sb.st_ctime;
  886.     close(lf);
  887. }
  888.  
  889. unlock(which)
  890. int which;
  891. {
  892. char *lockfile = which?translock:banklock;
  893. struct stat sb;
  894.  
  895.     if (!clock[which]) return;
  896.  
  897.     /* Check if it is my lock file */
  898.     if (stat(lockfile,&sb) || sb.st_ctime != clock[which])
  899.         printf("Warning: %s lock file has been blasted.\n",
  900.             which?"transaction":"bank");
  901.     /* If so, blast it */
  902.     else if (unlink(lockfile))
  903.         printf("Warning: Can't remove lockfile %s\n",lockfile);
  904.  
  905.     clock[which] = 0L;
  906. }
  907.  
  908. done(code)
  909. int code;
  910. {
  911.     if (clock[0]) unlock(0);
  912.     if (clock[1]) unlock(1);
  913.  
  914.     exit(code);
  915. }
  916. #else
  917. #endif LOCKFILE
  918.  
  919. /* Determine if the user "id" is a banker */
  920.  
  921. am_banker(id)
  922. char *id;
  923. {
  924. FILE *fp;
  925. int idlen = strlen(id);
  926. char buf[21];
  927.  
  928.     if ((fp=fopen(bankers,"r")) == NULL)
  929.     {
  930.         printf("cannot read %s\n",bankers);
  931.         return(0);
  932.     }
  933.  
  934.     while(fgets(buf,20,fp) != NULL)
  935.         if (!strncmp(id,buf,idlen))
  936.             return(1);
  937.     return(0);
  938. }
  939.